home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / xcdplayer / cdrom_sgi.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  25KB  |  1,134 lines

  1. /*
  2.  * Copyright (C) 1990 Regents of the University of California.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee,
  6.  * provided that the above copyright notice appear in all copies and that
  7.  * both that copyright notice and this permission notice appear in
  8.  * supporting documentation, and that the name of the University of
  9.  * California not be used in advertising or publicity pertaining to
  10.  * distribution of the software without specific, written prior
  11.  * permission.  the University of California makes no representations
  12.  * about the suitability of this software for any purpose.  It is provided
  13.  * "as is" without express or implied warranty.
  14.  */
  15.  
  16. static int c;
  17.  
  18. # if defined(sgi)
  19. # include <stdio.h>
  20.  
  21. # include <sys/file.h>
  22. # include <sys/types.h>
  23. # include <sys/param.h>
  24. # include <sys/stat.h>
  25.  
  26. # include <mntent.h>
  27. # include <string.h>
  28. # include <signal.h>
  29.  
  30. # include <sys/buf.h>
  31.  
  32. # include <sys/time.h>
  33.  
  34. /* We need shared memory for the counter display if using scsi_audio */
  35. #include <sys/ipc.h>
  36. #include <sys/shm.h>
  37. int        shmid;
  38. key_t        shmkey;
  39.  
  40.  
  41. # include "debug.h"
  42. # include "cdrom_sgi.h"
  43.  
  44. extern char    *device;
  45. # if defined(notdef)
  46. extern void    cdrom_print_toc();
  47. # endif /* defined(notdef) */
  48.  
  49. void        cdrom_audio_close();
  50. void        cdrom_callback();
  51. void        cdrom_kill_child();
  52. int        cdrom_child_setup();
  53. void        cdrom_child_pause();
  54. void        cdrom_child_died();
  55. void        cdrom_child_quit();
  56.  
  57. #define INIT_READ    200    /* Maximum number we can play */
  58. #define ONE_SECOND    75    /* One second of data */
  59.  
  60. cdrom_info        cdi;
  61. struct _cdrom_shmem    *cdrom_shmem;
  62. char            info_filename[256];
  63. FILE            *disc_info = NULL;
  64.  
  65. CDPLAYER    *cdrom_fd = NULL;
  66. ALport        audio_fd = NULL;
  67. long        audio_param[6];
  68. CDFRAME        *cd_audio_buff = NULL;
  69. CDPARSER    *cd_parser = NULL;
  70. int        cdrom_audio_opened = 0;
  71.  
  72. get_stored_info()
  73. {
  74.     int i,n;
  75.     char    line[100];
  76.     char    *title;
  77.  
  78.     if ( cdi.maxtrack == 0) {
  79.         return(0);
  80.     }
  81.     for (i = 0, n = 0; i < cdi.maxtrack; i++)
  82.         n = n + ((i+1) * cdi.times[i]);
  83.     n = n / cdi.maxtrack;
  84.  
  85.     disc_title = NULL;
  86.     if (cdInfoDir != NULL)
  87.         sprintf(info_filename, "%s/cd.%d", cdInfoDir, n);
  88.     else
  89.         sprintf(info_filename, "cd.%d", n);
  90.  
  91.     if ((disc_info = fopen(info_filename, "r")) != NULL)
  92.     {
  93.         fgets(line, 100, disc_info);
  94.         title = strchr(line, ':');
  95.         if (title != NULL)
  96.         {
  97.             *(strchr(title, '\n')) = '\0';
  98.             disc_title = strdup(title + 1);
  99.         }
  100.         fgets(line, 100, disc_info);
  101.         sscanf(line, "Program: %s", program_str);
  102.     }
  103.     if (disc_title == NULL) {
  104.         disc_title = NOTITLESTR;
  105.     }
  106. }
  107.  
  108. int
  109. cdrom_open() {
  110.     int        n;
  111.     CDSTATUS    cdrom_stat;
  112.     extern void update_title();
  113.  
  114.     if (cdrom_fd != NULL) {
  115.         return(cdi.curtrack);
  116.     }
  117.  
  118.     if (device != NULL) {
  119.         fprintf(stderr,"Device: %s\n",device);
  120.         if ((cdrom_fd = CDopen(device, "r")) == NULL) {
  121.             fprintf(stderr, "open cdrom: %s",device);
  122.             perror("CDopen");
  123.             return(-1);
  124.         }
  125.     } else {
  126.         if ((cdrom_fd = CDopen(0, "r")) == NULL) {
  127.             fprintf(stderr, "open cdrom: ");
  128.             perror("CDopen");
  129.             return(-1);
  130.         }
  131.     }
  132.  
  133.     if (cdrom_get_times() == -1) {
  134.         cdrom_close();
  135.         return(-1);
  136.     }
  137.  
  138.     if ((n = cdrom_get_curtrack()) == -1)
  139.         return(-1);
  140.  
  141.     get_stored_info();
  142.  
  143.     update_title();
  144.  
  145.     if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
  146.         fprintf(stderr, "CDgetstatus(cdrom_stat): ");
  147.         perror("CDgetstatus");
  148.         return(-1);
  149.     }
  150.     if ((cdrom_stat.state == CD_PLAYING) ||
  151.         (cdrom_stat.state == CD_PAUSED)) {
  152.         cdi.scsi_audio = 0;
  153.     } else {
  154.         cdi.scsi_audio = cdrom_audio_avail();
  155.     }
  156.  
  157.     if (cdi.scsi_audio) {
  158.         if (cd_audio_buff == (CDFRAME *) NULL) {
  159.             if ((cd_audio_buff =
  160.                  (CDFRAME *) malloc(INIT_READ * CDDA_BLOCKSIZE)) == NULL) {
  161.                 fprintf(stderr,"cdrom_open: cannot allocate cd digital data buffer!\n");
  162.                 perror("cdrom_open");
  163.                 cdi.scsi_audio = 0;
  164.             }
  165.         }
  166.         if (cd_parser == NULL) {
  167.             if ((cd_parser = CDcreateparser()) == NULL) {
  168.                 fprintf(stderr,"cdrom_open: CDcreateparser failed!\n");
  169.                 perror("cdrom_open");
  170.                 cdi.scsi_audio = 0;
  171.             }
  172.             CDresetparser(cd_parser);
  173.             CDsetcallback(cd_parser, cd_audio, cdrom_callback, 0);
  174.             CDsetcallback(cd_parser, cd_pnum, cdrom_callback, 0);
  175.             CDsetcallback(cd_parser, cd_atime, cdrom_callback, 0);
  176.             CDsetcallback(cd_parser, cd_catalog, cdrom_callback, 0);
  177.         }
  178. #if 0
  179.         /* Get the catalog number, if one exists */
  180.         CDseektrack(cdrom_fd,1);
  181.         cdrom_shmem->cdrom_audio_cdi.state = CD_PLAYING;
  182.         cdrom_play_frames(1);
  183. #endif
  184.     }
  185.  
  186.     if (cdi.state & CDROM_STATE_PLAY)
  187.         cdi.curtrack = n;
  188.  
  189.     if (cdi.state & CDROM_STATE_SHUFFLE)
  190.         shuffle_setup();
  191.  
  192.     return(cdi.curtrack);
  193. }
  194.  
  195. void
  196. cdrom_close() {
  197.     if (cdrom_fd == NULL)
  198.         return;
  199.  
  200.     if (cdi.scsi_audio) {
  201.         cdrom_kill_child();
  202.         cdrom_audio_close();
  203.     }
  204.     if (cdi.times != NULL) {
  205.         free((char *) cdi.times);
  206.         free((char *) cdi.addrs);
  207.         cdi.times = NULL;
  208.         cdi.addrs = NULL;
  209.     }
  210.  
  211.     (void) CDclose(cdrom_fd);
  212.     cdrom_fd = NULL;
  213. }
  214.  
  215. int
  216. cdrom_audio_open() {
  217.     ALconfig    aconfig;
  218.     
  219.     aconfig = ALnewconfig();
  220.  
  221.     /* Attempt to create the largest buffer we can */
  222.     ALsetqueuesize (aconfig, SAMPLES_PER_FRAME * INIT_READ);
  223.  
  224.     /* Make sure we are 16bit stereo */
  225.     ALsetwidth(aconfig, AL_SAMPLE_16);
  226.     ALsetchannels(aconfig, AL_STEREO);
  227.  
  228.     if ((audio_fd = ALopenport("XCplayer", "w", aconfig)) == NULL) {
  229.         ALfreeconfig(aconfig);
  230.         return(-1);    /* No error, just return -1 */
  231.     }
  232.     
  233.     ALfreeconfig(aconfig);
  234.  
  235.     audio_param[0] = AL_OUTPUT_RATE;
  236.     audio_param[1] = AL_RATE_44100;
  237.     ALsetparams(AL_DEFAULT_DEVICE, audio_param, 2);
  238.  
  239.     shmkey = IPC_PRIVATE;
  240.     if ((shmid = shmget(shmkey, sizeof(struct _cdrom_shmem), 
  241.                 (SHM_R | SHM_W | IPC_CREAT | IPC_EXCL) )) < 0) {
  242.         perror("shmget");
  243.         return(-1);
  244.     }
  245.     cdrom_shmem = shmat(shmid, NULL, SHM_RND);
  246. }
  247.  
  248. void
  249. cdrom_audio_close() {
  250.     if (audio_fd == NULL)
  251.         return;
  252.  
  253.     (void) ALcloseport(audio_fd);
  254.     shmdt(cdrom_shmem);
  255.     shmctl(shmid,IPC_RMID);
  256.     audio_fd = NULL;
  257.     cdrom_audio_opened = 0;
  258. }
  259.  
  260. void
  261. cdrom_callback(arg, type, data)
  262.     int        arg;
  263.     CDDATATYPES    type;
  264.     void        *data;
  265. {
  266.     struct cdtimecode    *timecode_info;
  267.     CDPROGNUM        *pnum_info;
  268.     char *            catalog_num;
  269.     int            otime, time;
  270.     int            i;
  271.  
  272.     switch (type) {
  273.     case cd_audio:
  274.         ALwritesamps(audio_fd, data, SAMPLES_PER_FRAME);
  275.         break;
  276.     case cd_pnum:
  277.         pnum_info = data;
  278.  
  279.         if (pnum_info->value <= 
  280.             cdrom_shmem->cdrom_audio_cdi.end_track) {
  281.             cdrom_shmem->cdrom_audio_cdi.curtrack = pnum_info->value;
  282.         } else {
  283.             cdrom_shmem->cdrom_audio_cdi.curtrack = 0;
  284.             cdrom_shmem->cdrom_audio_cdi.state = CD_READY;
  285.         }
  286.         break;
  287.     case cd_atime:
  288.         timecode_info = data;
  289.  
  290.         otime = (cdrom_shmem->cdrom_audio_msf.minute * 60) +
  291.             cdrom_shmem->cdrom_audio_msf.second;
  292.         time = (((timecode_info->mhi * 10) + 
  293.              timecode_info->mlo) * 60) +
  294.                  (timecode_info->shi * 10) +
  295.                      timecode_info->slo;
  296.  
  297.         if ((otime > (time + 2)) || (otime < time - 2)) {
  298.             if (CDseek(cdrom_fd, 
  299.                    cdrom_shmem->cdrom_audio_msf.minute,
  300.                    cdrom_shmem->cdrom_audio_msf.second, 
  301.                    cdrom_shmem->cdrom_audio_msf.frame) < 0) {
  302.                 perror("CDseek");
  303.             }
  304.             cdrom_shmem->cdrom_audio_cdi.state = CD_ABORT;
  305.             return;
  306.         }
  307.  
  308.         cdrom_shmem->cdrom_audio_msf.minute = 
  309.             (timecode_info->mhi * 10) + timecode_info->mlo;
  310.         cdrom_shmem->cdrom_audio_msf.second = 
  311.             (timecode_info->shi * 10) + timecode_info->slo;
  312.         cdrom_shmem->cdrom_audio_msf.frame = 
  313.             (timecode_info->fhi * 10) + timecode_info->flo;
  314.         
  315.         break;
  316.     case cd_catalog:
  317.         catalog_num = data;
  318. #if 0
  319.         fprintf(stderr,"Catalog #: ");
  320.         for (i=0; i<13; i++) {
  321.             fprintf(stderr,"%d",*(catalog_num+i));
  322.         }
  323.         fprintf(stderr,"\n");
  324. #endif
  325.     default:
  326.         return;
  327.     }
  328. }
  329.  
  330. int
  331. cdrom_start() {
  332.     return(0);
  333. }
  334.  
  335. int
  336. cdrom_stop() {
  337.     if (cdi.scsi_audio && cdrom_audio_opened) {
  338.         cdrom_kill_child();
  339.         cdrom_shmem->cdrom_audio_cdi.curtrack = cdi.curtrack;
  340.         cdrom_shmem->cdrom_audio_cdi.state = CD_READY;
  341.     }
  342.     if (! CDstop(cdrom_fd)) {
  343.         perror("CDstop");
  344.         return(-1);
  345.     }
  346.  
  347.     return(0);
  348. }
  349.  
  350. int
  351. cdrom_eject() {
  352.     if (cdi.scsi_audio && cdrom_audio_opened) {
  353.         cdrom_kill_child();
  354.         cdrom_shmem->cdrom_audio_cdi.state = CD_NODISC;
  355.     }
  356.     if (! CDeject(cdrom_fd)) {
  357.         perror("ioctl(cdromeject)");
  358.         return(-1);
  359.     }
  360.     cdrom_close();
  361.  
  362.     return(0);
  363. }
  364.  
  365. int
  366. cdrom_pause() {
  367.     int track;
  368.  
  369.     if (cdi.scsi_audio && cdrom_audio_opened) {
  370.         cdrom_shmem->cdrom_audio_cdi.state = CD_PAUSED;
  371.         return(0);
  372.     }
  373.     if (! cdrom_paused(&track)) {
  374.         if (! CDtogglepause(cdrom_fd)) {
  375.             perror("CDtogglepause");
  376.             return(-1);
  377.         }
  378.     }
  379.     
  380.     return(0);
  381. }
  382.  
  383. int
  384. cdrom_resume() {
  385.     int track;
  386.  
  387.     if (cdi.scsi_audio && cdrom_audio_opened) {
  388.         cdrom_shmem->cdrom_audio_cdi.state = CD_PLAYING;
  389.         return(0);
  390.     }
  391.     if (! cdrom_playing(&track)) {
  392.         if (! CDtogglepause(cdrom_fd)) {
  393.             perror("CDtogglepause");
  394.             return(-1);
  395.         }
  396.     }
  397.  
  398.     return(0);
  399. }
  400.  
  401. int
  402. cdrom_toggle_audio()
  403. {
  404.     if (cdi.scsi_audio) {
  405.         cdrom_kill_child();
  406.         cdi.scsi_audio = 0;
  407.         return;
  408.     }
  409.     cdi.scsi_audio = 1;
  410. }
  411.  
  412. int
  413. cdrom_volume(left_vol, right_vol)
  414.     int            left_vol;
  415.     int            right_vol;
  416. {
  417.     CDVOLUME    cd_vol;
  418.  
  419.     if (cdi.scsi_audio) {
  420.         audio_param[0] = AL_LEFT_SPEAKER_GAIN;
  421.         audio_param[1] = left_vol;
  422.         audio_param[2] = AL_RIGHT_SPEAKER_GAIN;
  423.         audio_param[3] = right_vol;
  424.  
  425.         ALsetparams (AL_DEFAULT_DEVICE, audio_param, 4);
  426.     } else {
  427. #if 0
  428.         /* I would love to use this, but it isn't documented */
  429.         cd_vol.chan0 = (unsigned char)left_vol;
  430.         cd_vol.chan1 = (unsigned char)right_vol;
  431.         CDsetvolume(cdrom_fd, &cd_vol);
  432. #endif
  433.         return(-1);
  434.     }
  435.  
  436.     return(0);
  437. }
  438.  
  439. int
  440. cdrom_get_volume()
  441. {
  442.     int vol;
  443.     CDVOLUME    cd_vol;
  444.  
  445.     audio_param[0] = AL_LEFT_SPEAKER_GAIN;
  446.     audio_param[2] = AL_RIGHT_SPEAKER_GAIN;
  447.     if (cdi.scsi_audio) {
  448.         ALgetparams (AL_DEFAULT_DEVICE, audio_param, 4);
  449.     
  450.         /* Return the average of left and right channels */
  451.         vol=(audio_param[1] + audio_param[3]) / 2;
  452.     } else {
  453. #if 0
  454.         /* I would love to use this, but it isn't documented */
  455.         CDgetvolume(cdrom_fd, &cd_vol);
  456.         fprintf(stderr,"%d %d %d %d\n",cd_vol.chan0,cd_vol.chan1,
  457.             cd_vol.chan2,cd_vol.chan3);
  458.         vol=(cd_vol.chan0 + cd_vol.chan1) / 2;
  459. #endif
  460.         vol = -1;
  461.     }
  462.  
  463.     return(vol);
  464. }
  465.  
  466. int
  467. cdrom_get_times() {
  468.     CDSTATUS            tochdr;
  469.     extern unsigned short    *ushort_malloc();
  470.     extern struct msf    *msf_malloc();
  471.     unsigned long        trk, trk_total, otime;
  472.     struct msf        msf;
  473.  
  474.     if (cdrom_read_tochdr(&tochdr) == -1) {
  475.         cdi.mintrack = 0;
  476.         cdi.maxtrack = 0;
  477.         return(-1);
  478. #if 0
  479.         return(0);
  480. #endif
  481.     }
  482.  
  483.     cdi.mintrack = tochdr.first;
  484.     cdi.maxtrack = tochdr.last;
  485.  
  486.     if (cdi.times != NULL)
  487.     {
  488.         free((char *) cdi.times);
  489.         free((char *) cdi.addrs);
  490.         cdi.times = NULL;
  491.         cdi.addrs = NULL;
  492.     }
  493.  
  494.     cdi.times = ushort_malloc(cdi.maxtrack - cdi.mintrack + 1);
  495.     cdi.addrs = msf_malloc(cdi.maxtrack - cdi.mintrack + 2);
  496.  
  497.     otime = 0;
  498.  
  499.     for (trk = cdi.mintrack; trk <= cdi.maxtrack; trk++) {
  500.         if (cdrom_get_msf(trk, &msf, &trk_total) == -1)
  501.             return(-1);
  502.  
  503.         /* record start address for each track (track 1 starts at 0)*/
  504.         cdi.addrs[trk - cdi.mintrack] = msf;
  505.  
  506.         trk_total -= otime;
  507.  
  508.         /* use start time of next track as length of previous */
  509.         if (otime != 0) 
  510.         {
  511.             cdi.times[trk - cdi.mintrack - 1] = trk_total;
  512.         }
  513.  
  514.         otime += trk_total;
  515.  
  516.     }
  517.  
  518.     /* find start of  leadout to get length of last track */
  519.     if (cdrom_get_msf(CDROM_LEADOUT, &msf, &trk_total) == -1)
  520.         return(-1);
  521.  
  522.     /* recode leadout start address */
  523.     cdi.addrs[trk - cdi.mintrack] = msf;
  524.     trk_total -= otime;
  525.     otime += trk_total;
  526.  
  527.     cdi.times[trk - cdi.mintrack - 1] = trk_total;
  528.  
  529.     return(0);
  530. }
  531.  
  532. # if defined(notdef)
  533. static void
  534. cdrom_print_toc() {
  535.     unsigned long        trk, trk_total;
  536.  
  537.     for (trk = cdi.mintrack; trk <= cdi.maxtrack; trk++) {
  538.         trk_total = cdi.times[trk - cdi.mintrack];
  539.         debug_printf(1, "%02u:%02u\n", trk_total/60, trk_total%60);
  540.     }
  541. }
  542. # endif /* defined(notdef) */
  543.  
  544. int
  545. cdrom_get_curtrack() {
  546.     CDSTATUS cdrom_stat;
  547.   
  548.     if (cdi.scsi_audio && cdrom_audio_opened &&
  549.         ((cdrom_shmem->cdrom_audio_cdi.state == CD_PLAYING) ||
  550.          (cdrom_shmem->cdrom_audio_cdi.state == CD_PAUSED))) {
  551.         if (((cdrom_shmem->cdrom_audio_msf.minute * 60) +
  552.              cdrom_shmem->cdrom_audio_msf.second) > 
  553.             ((cdi.addrs[cdrom_shmem->cdrom_audio_cdi.curtrack].minute * 60) +
  554.              cdi.addrs[cdrom_shmem->cdrom_audio_cdi.curtrack].second)) {
  555.             cdrom_shmem->cdrom_audio_cdi.curtrack++;
  556.         }
  557.         if (((cdrom_shmem->cdrom_audio_msf.minute * 60) +
  558.              cdrom_shmem->cdrom_audio_msf.second) < 
  559.             ((cdi.addrs[cdrom_shmem->cdrom_audio_cdi.curtrack-1].minute * 60) +
  560.              cdi.addrs[cdrom_shmem->cdrom_audio_cdi.curtrack-1].second)) {
  561.             cdrom_shmem->cdrom_audio_cdi.curtrack--;
  562.         }
  563.         return(cdrom_shmem->cdrom_audio_cdi.curtrack);
  564.     }
  565.     if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
  566.         fprintf(stderr, "CDgetstatus(cdrom_stat): ");
  567.         perror("CDgetstatus");
  568.         return(-1);
  569.     }
  570.  
  571.     switch (cdrom_stat.state) {
  572.     case CD_ERROR:
  573.         return(-1);
  574.         
  575.     case CD_NODISC:
  576.         debug_printf(1, "cdrom_get_curtrack: no disc\n");
  577.         return(0);
  578.         
  579.         /* playing track cdrom_stat.track */
  580.     case CD_PLAYING:
  581.         return((int) cdrom_stat.track);
  582.         
  583.         /* paused on track cdrom_stat.track */
  584.     case CD_PAUSED:
  585.         return((int) cdrom_stat.track);
  586.   
  587.         /* punt */
  588.     case CD_READY:
  589.         return(0);
  590.  
  591.         /* punt */
  592.     case CD_STILL:
  593.         return(0);
  594.  
  595. #if 0
  596.     case CD_NOSTATUS:
  597.         debug_printf(1, "cdrom_get_curtrack: no status\n");
  598.         return(0);
  599. #endif
  600.     }
  601.  
  602.     /* bad value in cdrom_stat */
  603.     return(-1);
  604. }
  605.  
  606. int
  607. cdrom_get_msf(track, msf, length)
  608.     unsigned long        track;
  609.     struct msf        *msf;
  610.     unsigned long        *length;
  611. {
  612.     struct cdrom_tocentry    tocentry;
  613.     
  614.     if (cdrom_read_tocentry(track, &tocentry) == -1)
  615.         return(-1);
  616.     
  617.     msf->minute = tocentry.cdte_addr.msf.minute;
  618.     msf->second = tocentry.cdte_addr.msf.second;
  619.     msf->frame = tocentry.cdte_addr.msf.frame;
  620.  
  621.     *length = ((int) tocentry.cdte_addr.msf.minute * 60) +
  622.         (int) tocentry.cdte_addr.msf.second;
  623.  
  624.     return(0);
  625. }
  626.  
  627. int
  628. cdrom_get_curmsf(msf)
  629.     struct msf *msf;
  630. {
  631.     int         num_frames;
  632.     CDSTATUS     cdrom_stat;
  633.  
  634.     if (cdi.scsi_audio && cdrom_audio_opened) {
  635.         msf->minute = cdrom_shmem->cdrom_audio_msf.minute;
  636.         msf->second = cdrom_shmem->cdrom_audio_msf.second;
  637.         msf->frame = cdrom_shmem->cdrom_audio_msf.frame;
  638.         if (msf->minute < 0) {
  639.             msf->minute = 0;
  640.             msf->second = 0;
  641.             msf->frame = 0;
  642.         }
  643.         return(0);
  644.     }
  645.     if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
  646.         fprintf(stderr, "CDgetstatus(cdrom_stat): ");
  647.         perror("CDgetstatus");
  648.         return(-1);
  649.     }
  650.     msf->minute = cdrom_stat.abs_min;
  651.     msf->second = cdrom_stat.abs_sec;
  652.     msf->frame = cdrom_stat.abs_frame;
  653.  
  654.     return (0);
  655. }
  656.  
  657. int
  658. cdrom_play_track(start_track, end_track)
  659.     unsigned char        start_track;
  660.     unsigned char        end_track;
  661. {
  662.     int         track;
  663.     struct msf     msf;
  664.  
  665.     track = start_track;
  666.     
  667.     if ( cdi.scsi_audio && cdrom_audio_opened ) {
  668.         cdrom_shmem->cdrom_audio_cdi.start_track = start_track;
  669.         cdrom_shmem->cdrom_audio_cdi.end_track = end_track;
  670.  
  671.         cdrom_shmem->cdrom_audio_cdi.state = CD_ABORT;
  672.         if (CDseektrack(cdrom_fd, track) < 0) {
  673.             perror("CDseektrack");
  674.             return(-1);
  675.         }
  676.         msf = cdi.addrs[track - cdi.mintrack];
  677.         cdrom_shmem->cdrom_audio_msf.minute = msf.minute;
  678.         cdrom_shmem->cdrom_audio_msf.second = msf.second;
  679.         cdrom_shmem->cdrom_audio_msf.frame = msf.frame;
  680.         cdi.curtrack = track;
  681.         cdrom_shmem->cdrom_audio_cdi.curtrack = track;
  682.         cdrom_shmem->cdrom_audio_cdi.state = CD_PLAYING;
  683.         if (cdrom_shmem->cdrom_audio_cdi.child_pid != 0) {
  684.             return(0);
  685.         }
  686.         signal(SIGCLD, cdrom_child_died);
  687.         if ((cdrom_shmem->cdrom_audio_cdi.child_pid = fork()) == 0) {
  688.             cdrom_child_setup();
  689.             while (1) {
  690.                 cdrom_play_frames(ONE_SECOND);
  691.             }
  692.         }
  693.     } else {
  694.         if (! CDplaytrack(cdrom_fd, track, 1)) {
  695.             perror("CDplaytrack");
  696.             return(-1);
  697.         }
  698.     }      
  699.  
  700.     return(0);
  701. }
  702.  
  703. int
  704. cdrom_play_msf(start_msf, end_msf)
  705.     struct msf    *start_msf;
  706.     struct msf    *end_msf;
  707. {
  708.     int num_frames;
  709.     int i;
  710.  
  711.     /* Fix negative seconds */
  712.     if (start_msf->second < 0) {
  713.         start_msf->second += 60;
  714.         start_msf->minute--;
  715.     }
  716.     
  717.     if ( cdi.scsi_audio && cdrom_audio_opened ) {
  718.         cdrom_shmem->cdrom_audio_msf.minute = start_msf->minute;
  719.         cdrom_shmem->cdrom_audio_msf.second = start_msf->second;
  720.         cdrom_shmem->cdrom_audio_msf.frame = start_msf->frame;
  721.         if (CDseek(cdrom_fd, start_msf->minute,
  722.                 start_msf->second, 
  723.                 start_msf->frame) < 0) {
  724.             perror("CDseek");
  725.             return(-1);
  726.         }
  727.         cdrom_shmem->cdrom_audio_cdi.state = CD_PLAYING;
  728.         cdrom_shmem->cdrom_audio_cdi.curtrack = cdi.curtrack;
  729.         if (cdrom_shmem->cdrom_audio_cdi.child_pid != 0) {
  730.             return(0);
  731.         }
  732.         signal(SIGCLD, cdrom_child_died);
  733.         if ((cdrom_shmem->cdrom_audio_cdi.child_pid = fork()) == 0) {
  734.             cdrom_child_setup();
  735.             while (1) {
  736.                 cdrom_play_frames(ONE_SECOND);
  737.             }
  738.         }
  739.  
  740.     } else {
  741.         if (! CDplayabs(cdrom_fd, start_msf->minute, 
  742.                 start_msf->second, 
  743.                 start_msf->frame, 1)) {
  744.             perror("CDplayabs");
  745.             return(-1);
  746.         }
  747.  
  748.         return(0);
  749.     }
  750. }
  751.  
  752. int
  753. cdrom_read_tocentry(track, tocentry)
  754.     unsigned int        track;
  755.     struct cdrom_tocentry     *tocentry;
  756. {
  757.     CDSTATUS cdrom_stat;
  758.     CDTRACKINFO cdrom_track;
  759.  
  760.     tocentry->cdte_track = track;
  761.     tocentry->cdte_format = CDROM_MSF;
  762.  
  763.     if (cdrom_status() == CD_NODISC) {
  764.         tocentry->cdte_addr.msf.minute = 0;
  765.         tocentry->cdte_addr.msf.second = 0;
  766.         tocentry->cdte_addr.msf.frame = 0;
  767.         return(0);
  768.     }
  769.  
  770.     if (track == CDROM_LEADOUT) {
  771.         if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
  772.             fprintf(stderr, "CDgetstatus(cdrom_read_tocentry): ");
  773.             perror("CDgetstatus");
  774.             return(-1);
  775.         }
  776.         tocentry->cdte_addr.msf.minute = cdrom_stat.total_min;
  777.         tocentry->cdte_addr.msf.second = cdrom_stat.total_sec;
  778.         tocentry->cdte_addr.msf.frame = cdrom_stat.total_frame;
  779.     } else {
  780.         if (! CDgettrackinfo(cdrom_fd, track, 
  781.                      (CDTRACKINFO *) &cdrom_track)) {
  782.             fprintf(stderr, "CDgettrackinfo(cdrom_read_tocentry): ");
  783.             perror("CDgetstatus");
  784.             return(-1);
  785.         }
  786.         tocentry->cdte_addr.msf.minute = cdrom_track.start_min;
  787.         tocentry->cdte_addr.msf.second = cdrom_track.start_sec;
  788.         tocentry->cdte_addr.msf.frame = cdrom_track.start_frame;
  789.     }
  790.     return(0);
  791. }
  792.  
  793. int
  794. cdrom_read_tochdr(tochdr)
  795.     CDSTATUS *tochdr;
  796. {
  797.     if (cdrom_status() == CD_NODISC) 
  798.         return(-1);
  799.  
  800.     if (! CDgetstatus(cdrom_fd, tochdr)) {
  801.         fprintf(stderr, "CDgetstatus(cdrom_read_tochdr): ");
  802.         perror("CDgetstatus");
  803.         return(-1);
  804.     }
  805.  
  806.     return(0);
  807. }
  808.  
  809. int
  810. cdrom_status() {
  811.     CDSTATUS cdrom_stat;
  812.  
  813.     if (cdrom_fd == NULL) {
  814.         return(-1);
  815.     }
  816.  
  817.     if (cdi.scsi_audio && cdrom_audio_opened &&
  818.         (cdrom_shmem->cdrom_audio_cdi.child_pid != 0)) { 
  819.         return(cdrom_shmem->cdrom_audio_cdi.state);
  820.     }
  821.     if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
  822.         fprintf(stderr, "CDgetstatus(cdrom_stat): ");
  823.         perror("CDgetstatus");
  824.         return(-1);
  825.     }
  826.  
  827.     switch (cdrom_stat.state) {
  828.     case CD_ERROR:
  829.         return(CD_ERROR);
  830.     case CD_NODISC:
  831.         return(CD_NODISC);
  832.     case CD_READY:
  833.         return(CD_READY);
  834.     case CD_PLAYING:
  835.         return(CD_PLAYING);
  836.     case CD_PAUSED:
  837.         return(CD_PAUSED);
  838.     case CD_STILL:
  839.         return(CD_STILL);
  840.     }
  841.  
  842.     return(-1);
  843. }
  844.  
  845. int
  846. cdrom_playing(track)
  847.     int            *track;
  848. {
  849.     CDSTATUS cdrom_stat;
  850.  
  851.     if (cdi.scsi_audio && cdrom_audio_opened &&
  852.         ((cdrom_shmem->cdrom_audio_cdi.state == CD_PLAYING) ||
  853.          (cdrom_shmem->cdrom_audio_cdi.state == CD_PAUSED))) {
  854.         return(cdrom_shmem->cdrom_audio_cdi.state);
  855.     }
  856.  
  857.     if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
  858.         fprintf(stderr, "CDgetstatus(cdrom_playing): ");
  859.         perror("CDstatus");
  860.         return(-1);
  861.     }
  862.  
  863.     *track = cdrom_stat.track;
  864.     if (cdrom_stat.state == CD_PLAYING) {
  865.         return(1);
  866.     }
  867.  
  868.     return(0);
  869. }
  870.  
  871. int
  872. cdrom_paused(track)
  873.     int            *track;
  874. {
  875.     CDSTATUS cdrom_stat;
  876.  
  877.     if (cdi.scsi_audio && cdrom_audio_opened &&
  878.         ((cdrom_shmem->cdrom_audio_cdi.state == CD_PLAYING) ||
  879.          (cdrom_shmem->cdrom_audio_cdi.state == CD_PAUSED))) {
  880.         return(cdrom_shmem->cdrom_audio_cdi.state);
  881.     }
  882.  
  883.     if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
  884.         fprintf(stderr, "CDgetstatus(cdrom_paused): ");
  885.         perror("CDgetstatus");
  886.         return(-1);
  887.     }
  888.  
  889.     *track = cdrom_stat.track;
  890.     if (cdrom_status() == CD_PAUSED) {
  891.         return(1);
  892.     }
  893.  
  894.     return(0);
  895. }
  896.  
  897. # if defined(notused)
  898. int
  899. mounted(name)
  900.     char        *name;
  901. {
  902.     char        buf[MAXPATHLEN], *cp;
  903.     struct stat    st;
  904.     dev_t        bdevno;
  905.     FILE        *fp;
  906.     struct mntent    *mnt;
  907.  
  908.     /*
  909.      * Get the block device corresponding to the raw device opened,
  910.      * and find its device number.
  911.      */
  912.     if (stat(name, &st) != 0) {
  913.         (void) fprintf(stderr, "stat: ");
  914.         perror(name);
  915.         return(UNMOUNTED);
  916.     }
  917.  
  918.     /*
  919.      * If this is a raw device, we have to build the block device name.
  920.      */
  921.     if ((st.st_mode & S_IFMT) == S_IFCHR) {
  922.         if ((cp = strchr(name, 'r')) != NULL)
  923.             cp++;
  924.  
  925.         (void) sprintf(buf, "/dev/%s", cp);
  926.         if (stat(buf, &st) != 0) {
  927.             (void) fprintf(stderr, "stat: ");
  928.             perror(buf);
  929.             return(UNMOUNTED);
  930.         }
  931.     }
  932.  
  933.     if ((st.st_mode & S_IFMT) != S_IFBLK)
  934.         return(UNMOUNTED);
  935.  
  936.     bdevno = st.st_rdev & (dev_t)(~0x07);    /* Mask out partition. */
  937.  
  938.     /*
  939.      * Now go through the mtab, looking at all hsfs filesystems.
  940.      * Compare the device mounted with our bdevno.
  941.      */
  942.     if ((fp = setmntent(MOUNTED, "r")) == NULL) {
  943.         (void) fprintf(stderr, "couldn't open %s\n", MOUNTED);
  944.         return(UNMOUNTED);
  945.     }
  946.  
  947.     while ((mnt = getmntent(fp)) != NULL) {
  948.         /* avoid obvious excess stat(2)'s */
  949.         if (strcmp(mnt->mnt_type, "hsfs") != 0)
  950.             continue;
  951.  
  952.         if (stat(mnt->mnt_fsname, &st) != 0)
  953.             continue;
  954.  
  955.         if (((st.st_mode & S_IFMT) == S_IFBLK) &&
  956.             ((st.st_rdev & (dev_t)(~0x07)) == bdevno)) {
  957.             (void) endmntent(fp);
  958.             return(STILL_MOUNTED);
  959.         }
  960.     }
  961.  
  962.     (void) endmntent(fp);
  963.  
  964.     return(UNMOUNTED);
  965. }
  966. # endif /* defined(notused) */
  967.  
  968. int
  969. cdrom_play_frames(number)
  970.     int    number;
  971. {
  972.     int    frames_to_read = number;
  973.     int    num_frames;
  974.     int    frame_ctr;
  975.     struct msf msf;
  976.     CDSTATUS cdrom_stat;
  977.  
  978.     if (cdrom_audio_opened && 
  979.         cdrom_shmem->cdrom_audio_cdi.state != CD_PLAYING) {
  980.         sleep(1);
  981.         return(-1);
  982.     }
  983.  
  984.     if (frames_to_read > INIT_READ) {
  985.         frames_to_read = INIT_READ;
  986.     }
  987.     if ((num_frames = 
  988.          CDreadda(cdrom_fd, &cd_audio_buff[0], frames_to_read)) == -1) {
  989.         perror("CDreadda");
  990.         return(-1);
  991.     }
  992.     if (num_frames == 0) {
  993.         msf = cdi.addrs[cdi.maxtrack];
  994.         if ((cdrom_shmem->cdrom_audio_msf.minute >= (msf.minute-1)) &&
  995.             (cdrom_shmem->cdrom_audio_msf.second >= (msf.second-1)) ) {
  996.             cdrom_shmem->cdrom_audio_cdi.curtrack = 0;
  997.             cdrom_shmem->cdrom_audio_cdi.state = CD_READY;
  998.         }
  999.         return(0);
  1000.     }
  1001.     for (frame_ctr=0;
  1002.          frame_ctr<num_frames && 
  1003.          cdrom_shmem->cdrom_audio_cdi.state == CD_PLAYING;
  1004.          frame_ctr++) {
  1005.         CDparseframe(cd_parser, &cd_audio_buff[frame_ctr]);
  1006.     }
  1007.     if (cdrom_shmem->cdrom_audio_cdi.state == CD_ABORT) {
  1008.         cdrom_shmem->cdrom_audio_cdi.state = CD_PLAYING;
  1009.     }
  1010.     return(num_frames);
  1011. }
  1012.  
  1013. int
  1014. cdrom_child_setup() {
  1015.     cdrom_shmem = shmat(shmid, NULL, SHM_RND);
  1016.     cdrom_shmem->cdrom_audio_cdi.state = CD_PLAYING;
  1017.     signal(SIGHUP,cdrom_child_quit);
  1018. }
  1019.  
  1020. void
  1021. cdrom_child_died() {
  1022.     cdrom_stop();
  1023.     wait(NULL);
  1024.     cdrom_shmem->cdrom_audio_cdi.child_pid = 0;
  1025.     cdrom_shmem->cdrom_audio_cdi.state = CD_READY;
  1026.     cdrom_shmem->cdrom_audio_cdi.curtrack = 0;
  1027.     cdi.curtrack = 0;
  1028.     cdrom_shmem->cdrom_audio_msf.minute = 0;
  1029.     cdrom_shmem->cdrom_audio_msf.second = 0;
  1030.     cdrom_shmem->cdrom_audio_msf.frame = 0;
  1031.     signal(SIGCLD,cdrom_child_died);
  1032. }
  1033.  
  1034. void
  1035. cdrom_child_quit() {
  1036.     shmdt(cdrom_shmem);
  1037.     exit(1);
  1038. }
  1039.  
  1040. void
  1041. cdrom_kill_child()
  1042. {
  1043.     if (!(cdrom_audio_opened && cdrom_shmem->cdrom_audio_cdi.child_pid)) {
  1044.         return;
  1045.     }
  1046.     kill(cdrom_shmem->cdrom_audio_cdi.child_pid, SIGHUP);
  1047.     wait(NULL);
  1048.     cdrom_shmem->cdrom_audio_cdi.state = CD_READY;
  1049.     cdrom_shmem->cdrom_audio_cdi.child_pid = 0;
  1050. }
  1051.  
  1052. int
  1053. cdrom_audio_avail() {
  1054.     CDSTATUS    cdrom_stat;
  1055.  
  1056.     if (cdrom_audio_opened && (! audio_button_state())) {
  1057.         return(0);
  1058.     }
  1059.     cdrom_audio_opened = 1;
  1060.  
  1061.     if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
  1062.         fprintf(stderr, "CDgetstatus(cdrom_stat): ");
  1063.         perror("CDgetstatus");
  1064.         return(-1);
  1065.     }
  1066.  
  1067.     if ( cdrom_stat.scsi_audio && (cdrom_audio_open() >= 0) ) {
  1068.         return(1);
  1069.     } else {
  1070.         return(0);
  1071.     }
  1072. }
  1073.  
  1074. unsigned short *
  1075. ushort_malloc(n)
  1076.     int        n;
  1077. {
  1078.     extern char    *calloc();
  1079.     unsigned short    *ptr;
  1080.  
  1081.     ptr = (unsigned short *) calloc(n, sizeof(unsigned short));
  1082.     if (ptr == NULL) {
  1083.         perror("calloc");
  1084.         exit(1);
  1085.     }
  1086.  
  1087.     return(ptr);
  1088. }
  1089.  
  1090. struct msf *
  1091. msf_malloc(n)
  1092.     int        n;
  1093. {
  1094.     extern char    *calloc();
  1095.     struct msf    *ptr;
  1096.  
  1097.     ptr = (struct msf *) calloc(n, sizeof(struct msf));
  1098.     if (ptr == NULL) {
  1099.         perror("calloc");
  1100.         exit(1);
  1101.     }
  1102.  
  1103.     return(ptr);
  1104. }
  1105.  
  1106. int
  1107. cdrom_disp_cdi() {
  1108.     int trk;
  1109.  
  1110.     fprintf(stderr,"CDI structure:\n");
  1111.     fprintf(stderr,"\tcurtrack: %d\n",cdi.curtrack);
  1112.     fprintf(stderr,"\tmin: %d  max: %d  total: %d\n",
  1113.         cdi.mintrack, cdi.maxtrack, cdi.ntracks);
  1114.     fprintf(stderr,"\tdur: %d  state: %2x\n",cdi.duration, cdi.state);
  1115.     fprintf(stderr,"\tcurrand: %d  lastprog: %d\n",
  1116.         cdi.currand, cdi.lastprog);
  1117.     fprintf(stderr,"\n\tTracklist:\n");
  1118.     if (cdi.maxtrack != cdi.mintrack) {
  1119.         for (trk=cdi.mintrack; trk<=cdi.maxtrack; trk++) {
  1120.             fprintf(stderr,"\t%3d: %d %02d:%02d %d\n",trk,cdi.times[trk],
  1121.                 cdi.addrs[trk].minute,cdi.addrs[trk].second,
  1122.                 cdi.addrs[trk].frame);
  1123.         }
  1124.     }
  1125.  
  1126.     if (cdi.scsi_audio) {
  1127.         fprintf(stderr,"AUDIO_CDI structure:\n");
  1128.         fprintf(stderr,"\tcurtrack: %d\n",cdrom_shmem->cdrom_audio_cdi.curtrack);
  1129.         fprintf(stderr,"\tdur: %d  state: %d\n",cdrom_shmem->cdrom_audio_cdi.duration, cdrom_shmem->cdrom_audio_cdi.state);
  1130.     }
  1131. }
  1132.  
  1133. # endif /* defined(sgi) */
  1134.